package com.spark.common.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.spark.common.exception.SparkException;
import com.spark.common.query.QueryGenerator;
import org.apache.commons.lang3.StringUtils;

/**
 * 树操作isLeaf字段工具类
 *  :是否叶子节点(0是1否)
 *
 * @author LYCHEE
 * @date 2025/2/18 13:41
 */
public class TreeIsLeafUtils<E> {

    /**
     * Service
     */
    private final IService<E> service;

    /**
     * Mapper
     */
    private final BaseMapper<E> mapper;

    /**
     * 模式，
     *  true：Service
     *  false: Mapper
     */
    private boolean mode = true;

    /**
     * 构造函数用于通过IService初始化服务实例
     * @param service 服务
     */
    public TreeIsLeafUtils(IService<E> service) {
        this.service = service;
        this.mapper = null;
        if (this.service == null){
            throw new SparkException("Service Not Find");
        }
    }

    /**
     * 构造函数用于通过IService初始化服务实例
     * @param service 服务
     * @param parentNodeField 父节点字段
     * @param isLeafNodeField 叶子节点字段
     */
    public TreeIsLeafUtils(IService<E> service, String parentNodeField, String isLeafNodeField) {
        this.mapper = null;
        this.service = service;
        this.parentNodeField = parentNodeField;
        this.isLeafNodeField = isLeafNodeField;
        if (this.service == null){
            throw new SparkException("Service Not Find");
        }
    }

    /**
     * 构造函数用于通过BaseMapper初始化映射器实例
     *
     * @param mapper MyBatis Plus 的 Mapper
     */
    public TreeIsLeafUtils(BaseMapper<E> mapper) {
        this.service = null;
        this.mode = false;
        this.mapper = mapper;
        if (this.mapper == null){
            throw new SparkException("Mapper Not Find");
        }
    }

    /**
     * 构造函数用于通过IService初始化服务实例
     * @param mapper 服务
     * @param parentNodeField 父节点字段
     * @param isLeafNodeField 叶子节点字段
     */
    public TreeIsLeafUtils(BaseMapper<E> mapper, String parentNodeField, String isLeafNodeField) {
        this.service = null;
        this.mode = false;
        this.mapper = mapper;
        this.parentNodeField = parentNodeField;
        this.isLeafNodeField = isLeafNodeField;
        if (this.mapper == null){
            throw new SparkException("Mapper Not Find");
        }
    }

    /**
     * 父节点字段名称
     */
    private String parentNodeField = "pid";

    /**
     * 叶子节点字段
     */
    private String isLeafNodeField = "isLeaf";

    /**
     * 泛型方法，处理树数据的IsLeaf
     * @param entity 实体
     * @param dealType 新增(add) 编辑(edit) 删除(del)
     * @param delId 删除时的ID
     */
    public void dealIsLeaf(E entity, String dealType, String delId) {
        // 新增
        if ("add".equals(dealType)){
            // 获取pid
            String pid = ReflectUtils.getField(entity, parentNodeField, String.class);
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(pid) && !"0".equals(pid)){
                // 查询父级数据
                E dataBaseEntity = this.getById(pid);
                // 当前父级是否是叶子节点，默认获取的是Boolean
                Boolean isLeafObj = ReflectUtils.getField(dataBaseEntity, isLeafNodeField, Boolean.class);
                if (!isLeafObj){
                    // 设置当前父级节点：不是叶子节点
                    ReflectUtils.setField(dataBaseEntity, isLeafNodeField, 1);
                    this.updateById(dataBaseEntity);
                }

            }
        }
        // 编辑
        if ("edit".equals(dealType)){
            // 获取id
            String id = ReflectUtils.getField(entity, "id", String.class);
            // 获取pid
            String pid = ReflectUtils.getField(entity, parentNodeField, String.class);
            // 根据id查询数据库
            E dataBaseEntity = this.getById(id);
            // 根据 dataBaseEntity 获取原来的pid
            String originalPid = ReflectUtils.getField(dataBaseEntity, parentNodeField, String.class);
            // 当 originalPid != pid 时,操作
            if (!pid.equals(originalPid)){
                // 是否需要更改原父级为叶子节点
                QueryWrapper<E> agoQueryWrapper = QueryGenerator.initQueryWrapper(entity);
                agoQueryWrapper.eq("pid", originalPid);
                long count = this.count(agoQueryWrapper);
                //List<T> list = service.list(agoQueryWrapper);
                if (count == 1){
                    // 更改父级节点为叶子节点
                    E agoDataBaseEntity = this.getById(originalPid);
                    ReflectUtils.setField(agoDataBaseEntity, isLeafNodeField, 0);
                    this.updateById(agoDataBaseEntity);
                }
                // 更改现有的父级ID
                QueryWrapper<E> currQueryWrapper = QueryGenerator.initQueryWrapper(entity);
                currQueryWrapper.eq("pid", pid);
                long count1 = this.count(currQueryWrapper);
                if (count1 == 0){
                    // 更改父级节点为非叶子节点
                    E currDataBaseEntity = this.getById(pid);
                    ReflectUtils.setField(currDataBaseEntity, isLeafNodeField, 1);
                    this.updateById(currDataBaseEntity);
                }
            }
        }
        // 删除
        if ("del".equals(dealType)){
            if (org.apache.commons.lang3.StringUtils.isEmpty(delId)){
                throw new SparkException("无法找到：delId");
            }
            E delEntity = this.getById(delId);
            // 当前是否是叶子节点，默认获取的是Boolean
            Boolean isLeafObj = ReflectUtils.getField(delEntity, isLeafNodeField, Boolean.class);
            if (isLeafObj){
                // 当前父级节点：不是叶子节点,无法删除
                throw new SparkException("无法删除非叶子节点");
            }
            // 获取pid
            String pid = ReflectUtils.getField(delEntity, parentNodeField, String.class);
            if (StringUtils.isNotEmpty(pid) && !"0".equals(pid)){
                QueryWrapper<E> currQueryWrapper = QueryGenerator.initQueryWrapper(delEntity);
                currQueryWrapper.eq("pid", pid);
                long currCount = this.count(currQueryWrapper);
                // 就这一个下级,更改父级为叶子节点
                if (currCount == 1){
                    E currParentEntity = this.getById(pid);
                    ReflectUtils.setField(currParentEntity, isLeafNodeField, 0);
                    this.updateById(currParentEntity);
                }
            }
        }
    }

    /**
     * 通过ID查询
     * @param id 主键
     * @return 实体
     */
    private E getById(String id) {
        if (this.mode){
            assert service != null;
            return service.getById(id);
        }else {
            assert mapper != null;
            return mapper.selectById(id);
        }
    }

    /**
     * 通过ID更新
     * @param entity 实体
     */
    private void updateById(E entity){
        if (this.mode){
            assert service != null;
            service.updateById(entity);
        }else {
            assert mapper != null;
            mapper.updateById(entity);
        }
    }

    /**
     * 查询数量
     * @param queryWrapper 条件
     * @return 数量
     */
    private long count(QueryWrapper<E> queryWrapper){
        if (this.mode){
            assert service != null;
            return service.count(queryWrapper);
        }else {
            assert mapper != null;
            return mapper.selectCount(queryWrapper);
        }
    }

}
